
package com.idealighter.game.games.wknh.manager;

import com.google.inject.Inject;
import com.google.inject.Singleton;

import com.idealighter.game.dictionary.dic.WknhBatteryDic;
import com.idealighter.game.dictionary.dic.WknhRoomDic;
import com.idealighter.game.dictionary.dic.WknhRoomTypeDic;
import com.idealighter.game.dictionary.domain.WknhBatteryDomain;
import com.idealighter.game.dictionary.domain.WknhRoomDomain;
import com.idealighter.game.gamehall.dto.MemInfo;
import com.idealighter.game.games.common.AbstractRoom;
import com.idealighter.game.games.common.AbstractSeat;
import com.idealighter.game.games.common.AbstractTable;
import com.idealighter.game.games.common.RoomState;
import com.idealighter.game.games.wknh.dto.BatteryInfo;
import com.idealighter.game.games.wknh.dto.FishDieInfo;
import com.idealighter.game.games.wknh.dto.RoomInfo;
import com.idealighter.game.games.wknh.dto.RoomTypeDetailInfo;
import com.idealighter.game.games.wknh.message.ResBatteryChangeMsg;
import com.idealighter.game.games.wknh.message.ResCancelLockMsg;
import com.idealighter.game.games.wknh.message.ResChipsChangeMsg;
import com.idealighter.game.games.wknh.message.ResEnterGameHallMsg;
import com.idealighter.game.games.wknh.message.ResEnterRoomMsg;
import com.idealighter.game.games.wknh.message.ResEnterTableMsg;
import com.idealighter.game.games.wknh.message.ResExitRoomMsg;
import com.idealighter.game.games.wknh.message.ResExitTableMsg;
import com.idealighter.game.games.wknh.message.ResFastEnterTableMsg;
import com.idealighter.game.games.wknh.message.ResFireMsg;
import com.idealighter.game.games.wknh.message.ResHitMsg;
import com.idealighter.game.games.wknh.message.ResInsteadPlayersUpgradeMsg;
import com.idealighter.game.games.wknh.message.ResLikuiUpgradeMsg;
import com.idealighter.game.games.wknh.message.ResLockMsg;
import com.idealighter.game.games.wknh.message.ResOtherEnterTableMsg;
import com.idealighter.game.games.wknh.message.ResProduceFishMsg;
import com.idealighter.game.games.wknh.message.ResScenceMsg;
import com.idealighter.game.games.wknh.message.ResSwitchSceneMsg;
import com.idealighter.game.games.wknh.struct.WknhFish;
import com.idealighter.game.games.wknh.struct.WknhRoom;
import com.idealighter.game.games.wknh.struct.WknhScence;
import com.idealighter.game.games.wknh.struct.WknhSeat;
import com.idealighter.game.games.wknh.struct.WknhTable;
import com.idealighter.game.message.core.ResMessage;
import com.idealighter.game.player.manager.PlayerMsgWriter;
import com.idealighter.game.player.struct.Player;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * 悟空闹海 .
 * 
 * @date 2016年3月7日 下午9:19:01
 *
 */
@Singleton
public class WknhMsgMgr {

  @Inject
  private PlayerMsgWriter msgWriter;
  @Inject
  private WknhDataMgr dataMgr;
  @Inject
  private WknhRoomTypeDic roomTypeDic;
  @Inject
  private WknhRoomDic roomDic;
  @Inject
  private WknhBatteryDic batteryDic;

  /**
   * 发送进入游戏大厅消息 .
   * 
   * @param player 玩家.
   */
  public void sendEnterGameHallMsg(Player player) {
    ResEnterGameHallMsg msg = new ResEnterGameHallMsg();

    Collection<WknhRoom> rooms = dataMgr.rooms();
    for (WknhRoom room : rooms) {
      WknhRoomDomain roomDom = roomDic.get(room.getId().intValue());
      if (roomDom.getIsActive() != 1) {
        continue;
      }

      if (player.fromPhone && roomDom.getPhone() != 1) {
        continue;
      }

      /*
       * if . (!player.fromPhone && roomDom.getPhone() == 1) { continue; }
       */
      // 机器人也可以进入手机房间
      if (!player.fromPhone && !player.robot() && roomDom.getPhone() == 1) {
        continue;
      }

      RoomTypeDetailInfo roomTypeDetailInfo = new RoomTypeDetailInfo();

      roomTypeDetailInfo.setType(roomDom.getType());
      roomTypeDetailInfo.setTypeName(roomTypeDic.map().get(roomDom.getType()).getName());

      RoomInfo roomInfo = new RoomInfo();
      roomInfo.setRoomId(room.getId().intValue());
      roomInfo.setName(roomDom.getName());
      roomInfo.setType(roomDom.getType());
      roomInfo.setMaxNum(roomDom.getMaxNum());
      roomInfo.setFree(roomDom.getFree());
      roomInfo.setGeneral(roomDom.getGeneral());
      roomInfo.setCrowded(roomDom.getCrowded());
      roomInfo.setLower(roomDom.getLower());
      roomInfo.setUpper(roomDom.getUpper());
      roomInfo.setProportionGold(roomDom.getProportionGold());
      roomInfo.setProportionChips(roomDom.getProportionChips());
      roomInfo.setTabble(roomDom.getTable());
      roomInfo.setAfee(roomDom.getAfee());
      roomInfo.setInType(roomDom.getInType());
      roomInfo.setPlayerNum(room.getPlayers().size());
      roomInfo.setStatus(roomStatus(room).desc);
      roomInfo.setDisplayNames(roomDom.getDisplays());
      roomInfo.setPlaceHolder(roomDom.getPlaceHolder());
      roomTypeDetailInfo.getRooms().add(roomInfo);

      msg.getRoomTypes().add(roomTypeDetailInfo);
    }

    msgWriter.writeMsg(player, msg);
  }

  /**
   * 房间状态，空闲,普通,拥挤,爆满 .
   * 
   * @param room .
   * @return
   */
  private RoomState roomStatus(WknhRoom room) {
    int playersNum = room.getPlayers().size();
    WknhRoomDomain roomDom = roomDic.get(room.getId().intValue());

    if (playersNum < roomDom.getMaxNum() * roomDom.getFree() / 100) {
      return RoomState.IDLE;
    } else if (playersNum < roomDom.getMaxNum() * roomDom.getGeneral() / 100) {
      return RoomState.GENERAL;
    } else if (playersNum < roomDom.getMaxNum() * roomDom.getCrowded() / 100) {
      return RoomState.CROWD;
    } else {
      return RoomState.FULL;
    }

  }

  /**
   * 发送进入桌子消息 .
   * 
   * @param player 玩家.
   */
  public void sendEnterRoomMsg(Player player) {
    ResEnterRoomMsg msg = new ResEnterRoomMsg();
    for (AbstractTable table : player.curRoom.tables()) {
      msg.getTables().add(table.tableInfo());
    }
    msg.setMembers(player.curRoom.memInfos());
    msgWriter.writeMsg(player, msg);
  }

  /**
   * 发送兑换筹码消息 .
   * 
   * @param seat 座位信息.
   */
  public void sendChipsChangeMsg(WknhSeat seat) {
    ResChipsChangeMsg msg = new ResChipsChangeMsg();
    msg.setPlayerId(seat.getPlayerId());
    msg.setChips(seat.getTotalChips());
    msg.setOrder(seat.getOrder());
    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 发送快速进入结果消息 .
   * 
   * @param player 玩家.
   * @param res 0:成功,1:没有空位置
   */
  public void sendFastEnterTableMsg(Player player, int res) {
    ResFastEnterTableMsg msg = new ResFastEnterTableMsg();
    msg.setRes(res);
    msgWriter.writeMsg(player, msg);
  }

  /**
   * 发送进入桌子消息 .
   * 
   * @param player 玩家.
   * @param table .
   */
  public void sendEnterTableMsg(Player player, WknhTable table) {
    ResEnterTableMsg msg = new ResEnterTableMsg();
    AbstractRoom room = table.room();
    List<MemInfo> mems = new ArrayList<>();
    for (Long playerId : table.players()) {
      mems.add(room.memInfo(playerId));
    }
    msg.setMems(mems);

    msgWriter.writeMsg(player, msg);
  }

  /**
   * 发送场景数据消息 .
   * 
   * @param player 玩家.
   * @param table .
   */
  public void sendScenceMsg(Player player, WknhTable table) {
    WknhScence scence = table.scence();
    ResScenceMsg msg = new ResScenceMsg();
    msg.setScenceId(table.scence().id);
    for (WknhFish fish : scence.fishs.values()) {
      if (fish.alive()) {
        msg.getFishs().add(fish.finshInfo());
      }
    }

    for (WknhSeat seat : table.seats) {
      if (seat.getPlayerId() > 0) {
        msg.getBatterys().add(batteryInfo(seat));
      }
    }

    if (table.leader == player.getId()) { // 队长代发机器人碰撞
      List<Long> insteadPlayers = msg.getInsteadPlayers();
      for (WknhSeat s : table.seats) {
        if (s.isRobot() && s.getPlayerId() > 0) {
          insteadPlayers.add(s.getPlayerId());
        }
      }
    }

    msgWriter.writeMsg(player, msg);
  }

  /**
   * 发送代码碰撞玩家列表更新消息 .
   * 
   * @param table .
   */
  public void sendInsteadPlayersUpgradeMsg(WknhTable table) {
    ResInsteadPlayersUpgradeMsg msg = new ResInsteadPlayersUpgradeMsg();
    List<Long> insteadPlayers = msg.getInsteadPlayers();
    for (WknhSeat s : table.seats) {
      if (s.isRobot() && s.getPlayerId() > 0) {
        insteadPlayers.add(s.getPlayerId());
      }
    }

    msgWriter.writeMsg(table.leader, msg);
  }

  /**
   * 发送其他人进入桌子消息 .
   * 
   * @param seat 座位信息.
   */
  public void sendOtherEnterTableMsg(WknhSeat seat) {
    ResOtherEnterTableMsg msg = new ResOtherEnterTableMsg();
    msg.setBattery(batteryInfo(seat));
    msg.setMem(seat.table.room.memInfo(seat.getPlayerId()));
    for (Long playerId : seat.table.players()) {
      if (playerId != seat.getPlayerId()) {
        msgWriter.writeMsg(playerId, msg);
      }
    }
  }

  /**
   * 发送退出房间消息 .
   * 
   * @param player 玩家.
   * @param res 0:退出成功,1:在牌桌中退出失败
   */
  public void sendExitRoomMsg(Player player, int res) {
    ResExitRoomMsg msg = new ResExitRoomMsg();
    msg.setRes(res);
    msgWriter.writeMsg(player, msg);
  }

  /**
   * 发送退出桌子消息 .
   * 
   * @param seat 座位信息.
   */
  public void sendExitTableMsg(WknhSeat seat) {
    ResExitTableMsg msg = new ResExitTableMsg();
    msg.setOrder(seat.getOrder());
    msg.setPlayerId(seat.getPlayerId());
    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 发送开炮结果消息 .
   * 
   * @param seat 座位信息.
   * @param bulletId .
   * @param angle .
   */
  public void sendFireMsg(WknhSeat seat, int bulletId, int angle) {
    ResFireMsg msg = new ResFireMsg();
    msg.setOrder(seat.getOrder());
    msg.setPlayerId(seat.getPlayerId());
    msg.setAngle(angle);
    msg.setBulletId(bulletId);

    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 发送切换炮台消息 .
   * 
   * @param seat 座位信息.
   */
  public void sendBatteryChangeMsg(WknhSeat seat) {
    ResBatteryChangeMsg msg = new ResBatteryChangeMsg();
    msg.setBattery(batteryInfo(seat));

    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 炮台信息 .
   * 
   * @param seat 座位信息.
   * @return
   */
  private BatteryInfo batteryInfo(WknhSeat seat) {
    WknhBatteryDomain batteryDom = batteryDic.get(seat.batteryId);
    BatteryInfo batteryInfo = new BatteryInfo();
    batteryInfo.setNum(batteryDom.getNum());
    batteryInfo.setScore(batteryDom.getScore());
    batteryInfo.setOrder(seat.getOrder());
    batteryInfo.setPlayerId(seat.getPlayerId());
    batteryInfo.setPower(seat.power ? 1 : 0);

    return batteryInfo;
  }

  /**
   * 发送切换场景 .
   * 
   * @param table .
   * @param scenceIndex .
   */
  public void sendSwitchSceneMsg(WknhTable table, int scenceIndex) {
    ResSwitchSceneMsg msg = new ResSwitchSceneMsg();
    msg.setScene(table.scences.get(scenceIndex).id);
    sendTablePlayersMsg(table, msg);
  }

  /**
   * 发送子弹打中消息 .
   * 
   * @param seat 座位信息.
   * @param fishScores . 被打死的鱼分数(key：鱼id,val:鱼的分数)
   */
  public void sendHitsMsg(WknhSeat seat, Map<Integer, Integer> fishScores) {
    ResHitMsg msg = new ResHitMsg();
    msg.setPlayerId(seat.getPlayerId());
    msg.setOrder(seat.getOrder());
    for (Entry<Integer, Integer> diedFishScore : fishScores.entrySet()) {
      FishDieInfo dieInfo = new FishDieInfo();
      dieInfo.setFishId(diedFishScore.getKey());
      dieInfo.setScore(diedFishScore.getValue());
      msg.getDies().add(dieInfo);
    }

    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 发送锁定鱼 .
   * 
   * @param seat 座位信息.
   * @param fishId .
   */
  public void sendLockMsg(WknhSeat seat, int fishId) {
    ResLockMsg msg = new ResLockMsg();
    msg.setPlayerId(seat.getPlayerId());
    msg.setOrder(seat.getOrder());
    msg.setFishId(fishId);
    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 发送取消锁定消息 .
   * 
   * @param seat 座位信息.
   */
  public void sendCancelLockMsg(WknhSeat seat) {
    ResCancelLockMsg msg = new ResCancelLockMsg();
    msg.setPlayerId(seat.getPlayerId());
    msg.setOrder(seat.getOrder());
    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 发送产生鱼消息 .
   * 
   * @param table .
   */
  public void sendProduceFishMsg(WknhTable table, List<WknhFish> fishs) {
    ResProduceFishMsg msg = new ResProduceFishMsg();
    for (WknhFish fish : fishs) {
      msg.getFishs().add(fish.finshInfo());
    }

    sendTablePlayersMsg(table, msg);
  }

  /**
   * 发送李逵升级消息 .
   * 
   * @param room .
   * @param likuiRate .
   */
  public void sendLikuiUpgradeMsg(WknhRoom room, int likuiRate) {
    ResLikuiUpgradeMsg msg = new ResLikuiUpgradeMsg();
    msg.setRate(likuiRate);
    msg.setFishId(room.likui);

    sendRoomPlayersMsg(room, msg);
  }

  /**
   * 单个玩家发送李逵升级消息 .
   * 
   * @param seat 座位信息.
   */
  public void sendLikuiUpgradeMsg(WknhSeat seat) {
    WknhRoom room = seat.table.room;
    ResLikuiUpgradeMsg msg = new ResLikuiUpgradeMsg();
    msg.setRate(room.likuiMultiple());
    msg.setFishId(room.likui);
    msgWriter.writeMsg(seat.getPlayerId(), msg);
  }

  /**
   * 向同桌的玩家(包括自己)发送消息 .
   * 
   * @param table .
   * @param msg .
   */
  public void sendTablePlayersMsg(WknhTable table, ResMessage msg) {
    List<? extends AbstractSeat> seats = table.seats();
    for (int i = 0; i < seats.size(); i++) {
      AbstractSeat seat = seats.get(i);
      long playerId = seat.getPlayerId();
      if (playerId > 0) {
        msgWriter.writeMsg(playerId, msg);
      }
    }
  }

  /**
   * 向同房间的玩家(包括自己)发送消息 .
   * 
   * @param room .
   * @param msg .
   */
  public void sendRoomPlayersMsg(WknhRoom room, ResMessage msg) {
    for (Long p : room.getPlayers()) {
      msgWriter.writeMsg(p, msg);
    }
  }
}
